package trading.algo.BearTask;

import java.util.List;
import java.util.Timer;
import java.util.TimerTask;

import trading.algo.OptionMktOrderTask;
import trading.algo.TimerKillerTask;
import trading.bo.EmailAccessorBO;
import trading.bo.IBAccessorBO;
import trading.dataentry.OptionPositionOrOrder;

public class SyncOptionPositionAndOrderTask extends TimerTask{

	private List<OptionPositionOrOrder> optionOrders;
	private List<OptionPositionOrOrder> optionPositions;
	private IBAccessorBO ibAccessorBO;
	private EmailAccessorBO emailAccessorBO;
	
	public SyncOptionPositionAndOrderTask(List<OptionPositionOrOrder> optionOrders, List<OptionPositionOrOrder> optionPositions, IBAccessorBO ibAccessorBO, EmailAccessorBO emailAccessorBO) {
		this.optionOrders = optionOrders;
		this.optionPositions = optionPositions;
		this.ibAccessorBO = ibAccessorBO;
		this.emailAccessorBO = emailAccessorBO;
	}
	
	@Override
	public void run() {
		this.syncOptionPositionAndOrder(optionPositions, optionOrders);
	}
	
	/**
	 * Make sure all option position has corresponding order covered.
	 * 
	 * @param optionPositions
	 * @param optionOrders
	 */
	private void syncOptionPositionAndOrder(List<OptionPositionOrOrder> optionPositions, List<OptionPositionOrOrder> optionOrders) {
		Timer timer = new Timer();
		int taskID = 0;
    	for (OptionPositionOrOrder optionPosition : optionPositions) {
    		int size = Integer.parseInt(optionPosition.getPosition());
    		for (OptionPositionOrOrder optionOrder : optionOrders) {
    			if (optionPosition.getUnderlyingTick().equals(optionOrder.getUnderlyingTick()) 
    					&& optionPosition.getCallOrPut().equals(optionOrder.getCallOrPut())
    					&& optionPosition.getExpiration().equals(optionOrder.getExpiration())
    					&& optionPosition.getStrikePrice().equals(optionOrder.getStrikePrice())) {
    				int orderSize = Integer.parseInt(optionOrder.getPosition());
    				if (optionOrder.getAction() == "SELL") {
    					orderSize *= -1;
    				}
    				size += orderSize;
    			}
    		}
    		String orderExpiration = optionPosition.getExpiration().substring(0, "yyyyMM".length());
    		double strikePrice = Double.parseDouble(optionPosition.getStrikePrice());
    		if (size > 0) {
    			// create mkt option sell order
    			OptionMktOrderTask optionMktOrderTask = new OptionMktOrderTask(this.ibAccessorBO, emailAccessorBO, "SELL", size, "MKT", optionPosition.getUnderlyingTick(), orderExpiration, strikePrice, optionPosition.getCallOrPut());
    			timer.schedule(optionMktOrderTask, taskID * 1000);
    			taskID += OptionMktOrderTask.secondsNeeded();
    		} else if (size < 0) {
    			// create mkt option buy order
    			OptionMktOrderTask optionMktOrderTask = new OptionMktOrderTask(this.ibAccessorBO, emailAccessorBO, "BUY", size * -1, "MKT", optionPosition.getUnderlyingTick(), orderExpiration, strikePrice, optionPosition.getCallOrPut());
    		    timer.schedule(optionMktOrderTask, taskID * 1000);
    		    taskID += OptionMktOrderTask.secondsNeeded();
    		}
    	}
    	TimerKillerTask timerKillerTask = new TimerKillerTask(timer);
    	timer.schedule(timerKillerTask, taskID * 1000);
    }

	public static int secondsNeeded() {
	    return 10 * OptionMktOrderTask.secondsNeeded() + 2;
	}
}
